package com.aqie.arithmetic.math;


import com.aqie.libs.StdOut;
import com.aqie.libs.StdRandom;

import java.util.Arrays;

public class MyMath<T> {
    // 1,判断一个数是否是素数
    public static boolean isPrime(int N){
        if (N < 2) return false;
        for (int i = 2; i * i <= N; i++){
            if (N % i == 0) return false;
        }
        return true;
    }

    // 2, 计算平方根 （牛顿迭代法）
    public static double sqrt(double c){
        if (c < 0) return Double.NaN;
        double err = 1e-15;
        double t = c;
        while (Math.abs(t - c / t) > err){
            t = (c / t + t) / 2.0;
        }
        return t;
    }

    // 3. 调和级数
    public static double harmonicSeries(int N){
        double sum = 0.0;
        for (int i = 0; i <= N; i++){
            sum += 1.0 / i;
        }
        return sum;
    }

    // 4. 根据离散概率 随机返回 int 值
    public static int discrete(double[] a){
        // a 中各元素和必须等于1
        double r = StdRandom.uniform();
        double sum = 0.0;
        for (int i = 0; i < a.length; i++){
            sum = sum + a[i];
            if (sum >= r) return i;
        }
        return -1;
    }

    // 随机将dopuble 数组中元素排序
    public static void shuffle(double[] a){
        int N = a.length;
        for (int i = 0; i < N; i++){
          // 将 a[i] 与 a[i..N-1] 中任意一个元素交换
          int r = i + StdRandom.uniform(N - i);
          double tmp = a[i];
          a[i] = a[r];
          a[r] = tmp;
        }
    }

    public void p(T t){
        System.out.println(t);
    }

    public static void main(String[] args) {

        MyMath math = new MyMath();

        System.out.println(2E2);  // 2 * 10 ^ 2
        System.out.println(1E-2); // 2 * 10 ^ (-2)
        System.out.println(sqrt(5));

        double a = 3, b = 4;
        // 数学 API
        Math.abs(3);
        Math.max(3, 4);
        Math.min(3, 4);


        math.p(Math.sin(Math.PI / 2));      // 1
        math.p(Math.asin(Math.PI / 4));     // 0.9

        math.p(Math.cos(Math.PI / 2));      // 0
        math.p(Math.tan(Math.PI / 4));      // 1

        // toDegrees()  toRadians()
        math.p(Math.exp(1)); // e^1  2.718
        math.p(Math.log(Math.exp(2))); // 2

        double[] d = {0.1, 0.2, 0.3,0.4};
        System.out.println(discrete(d));
        shuffle(d);
        System.out.println(Arrays.toString(d));

        // double 无穷大
        StdOut.println(Double.POSITIVE_INFINITY);
        StdOut.println(1.0/0.0);

        // 余数定义, 负数的除法和余数 结果 ： a/b 的商会向0取整
        StdOut.println((a/b) * b + a % b);   // 6.0

        test();
    }

    public static void test(){
        StdOut.println((0 + 15) / 2);
        StdOut.println(2.0e-6 * 100000000.1);   // 200.0000002
        StdOut.println(true && false || true && true);
        StdOut.println((1 + 2.236) / 2);        // 1.618
        StdOut.println(1 + 2 + 3 + 4.0);        // 10.0
    }
}
